package future

type Future interface {
	IsDone() bool
	Complete(interface{})
	CompleteExceptionally(error)
	Get() (interface{}, error)
}

type future struct {
	Future
	err    error
	result interface{}
	done   chan bool
}

func (f *future) IsDone() bool {
	select {
	case <-f.done:
		return true
	default:
		return false
	}
}

func (f *future) Complete(result interface{}) {
	if f.IsDone() {
		return
	}
	f.result = result
	close(f.done)
}

func (f *future) CompleteExceptionally(err error) {
	if f.IsDone() {
		return
	}
	f.err = err
	close(f.done)
}

func (f *future) Get() (interface{}, error) {
	if f.IsDone() {
		return f.result, f.err
	}

	// wait for complete
	<-f.done
	return f.result, f.err
}

func NewFuture() Future {
	return &future{
		done: make(chan bool),
	}
}
